package org.adream.account.util;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.TransferManagerConfiguration;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author fatDog
 */
public class CosFileUtil {
    private COSClient cosClient;
    private TransferManager transferManager;
    private static String secretId;
    private static String secretKey;
    private static String bucketName;

    private static String cosRegion;


    static {
        //加载需要的配置文件
        secretId = Utils.readProperty("config/info.properties", "cos.SecretId");
        secretKey = Utils.readProperty("config/info.properties", "cos.SecretKey");
        bucketName = Utils.readProperty("config/info.properties", "cos.bucketName");
        cosRegion = Utils.readProperty("config/info.properties", "cos.region");

    }

    private static CosFileUtil cosUtil = null;

    private CosFileUtil() {
        this.initClient();
    }

    private void initClient() {
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region(cosRegion);
        ClientConfig clientConfig = new ClientConfig(region);
        // 3 生成 cos 客户端。
        this.cosClient = new COSClient(cred, clientConfig);
        // 高级接口传输类
        // 线程池大小，建议在客户端与 COS 网络充足（例如使用腾讯云的 CVM，同地域上传 COS）的情况下，设置成16或32即可，可较充分的利用网络资源
        // 对于使用公网传输且网络带宽质量不高的情况，建议减小该值，避免因网速过慢，造成请求超时。
        ExecutorService threadPool = Executors.newFixedThreadPool(4);
        // 传入一个 threadpool, 若不传入线程池，默认 TransferManager 中会生成一个单线程的线程池。
        transferManager = new TransferManager(cosClient, threadPool);
        // 设置高级接口的分块上传阈值和分块大小为10MB
        TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
        transferManagerConfiguration.setMultipartUploadThreshold(10 * 1024 * 1024);
        transferManagerConfiguration.setMinimumUploadPartSize(10 * 1024 * 1024);
        transferManager.setConfiguration(transferManagerConfiguration);
    }

    public static CosFileUtil getSingle() {
        synchronized (CosFileUtil.class) {
            if (cosUtil == null) {
                cosUtil = new CosFileUtil();
            }
            return cosUtil;
        }
    }

    /**
     * 简单上传对象
     */
    public void putObjectFlex(String key, InputStream inputStream) throws InterruptedException, IOException, NoSuchAlgorithmException {
        key = this.path2Oss(key);
        //.cssg-snippet-body-start:[put-object-flex]
        // Bucket的命名格式为 BucketName-APPID ，此处填写的存储桶名称必须为此格式
        ObjectMetadata objectMetadata = new ObjectMetadata();
        // 设置输入流长度为500
        //objectMetadata.setContentLength(500);
        // 设置 Content type, 默认是 application/octet-stream
//        System.out.println("bucketName:"+ bucketName);
//        System.out.println("key:"+ key);
        PutObjectResult putObjectResult = cosClient.putObject(bucketName, key, inputStream, objectMetadata);
    }

    public void getObject(String key, HttpServletResponse response, int width, int height) throws IOException {
        key = this.path2Oss(key);
        // 方法1 获取下载输入流
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
        // 限流使用的单位是 bit/s, 这里设置下载带宽限制为10MB/s
        getObjectRequest.setTrafficLimit(80 * 1024 * 1024);
        String rule = "";
        if (width > 0 && height > 0) {
            rule = "imageMogr2/thumbnail/" + width + "x" + height + ">";
        } else if (width > 0) {
            rule = "imageMogr2/thumbnail/" + width + "x";
        } else if (height > 0) {
            rule = "imageMogr2/thumbnail/x" + height;
        }
        //图片处理失败，返回原图
        getObjectRequest.putCustomQueryParameter("/ignore-error/1", null);
        getObjectRequest.putCustomQueryParameter(rule, null);
        COSObject cosObject = cosClient.getObject(getObjectRequest);
        COSObjectInputStream cosObjectInput = cosObject.getObjectContent();
        try (OutputStream os = response.getOutputStream()) {
            int count;
            byte[] buffer = new byte[1024 * 8];
            while ((count = cosObjectInput.read(buffer)) != -1) {
                os.write(buffer, 0, count);
                os.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        cosObjectInput.close();
    }

    public void downFile(String key, HttpServletResponse response) throws IOException {
        key = this.path2Oss(key);
        // 方法1 获取下载输入流
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
        // 限流使用的单位是 bit/s, 这里设置下载带宽限制为10MB/s
        getObjectRequest.setTrafficLimit(80 * 1024 * 1024);
        COSObject cosObject = cosClient.getObject(getObjectRequest);
        COSObjectInputStream cosObjectInput = cosObject.getObjectContent();
        response.setContentType("multipart/form-data");
        /* 设置文件头：最后一个参数是设置下载文件名 */
        response.setHeader("Content-Disposition",
                "filename=" + new String(new File(key).getName().getBytes("UTF-8"), "ISO8859-1"));
        try (OutputStream os = response.getOutputStream()) {
            int count;
            byte[] buffer = new byte[1024 * 8];
            while ((count = cosObjectInput.read(buffer)) != -1) {
                os.write(buffer, 0, count);
                os.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        cosObjectInput.close();
    }

    private String path2Oss(String oriPath) {
        String[] readyPathList = oriPath.split(":");
        String path;
        if (readyPathList.length > 1) {
            path = readyPathList[1];
        } else {
            path = readyPathList[0];
        }
        path = path.replaceAll("\\\\", "/");
        if (path.startsWith("/")) {
            path = path.replaceFirst("/", "");
        }
        return path;
    }


}